/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package iconeLibrary.controler;

import iconeLibrary.model.Connection;
import iconeLibrary.model.XQueryRequest;
import iconeLibrary.controler.TypeImage;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletOutputStream;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.batik.dom.util.SAXDocumentFactory;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.batik.transcoder.image.TIFFTranscoder;
import org.apache.batik.util.XMLResourceDescriptor;
import org.apache.xerces.dom.DOMImplementationImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xmldb.api.base.XMLDBException;

/**
 *
 * @author Ayede Sonia :: Gaudino Anthony :: Herche Bilal :: Teixeira Tiago :: Touati Samed  :: Wadjahdi Marc
 */
public class Controler {

    private static final long serialVersionUID = 4726581784877047255L;
    public static final String queryIconesNamesFilePath = "../ressources/queryIconesNames.xq";
    public static final String queryFiltersNamesFilePath = "../ressources/queryFiltersNames.xq";
    public static final String getSubIconeByNameRequestPath = "../ressources/getSubIconeByName.xq";
    public static final String getIconeByNameRequestPath = "../ressources/getIconeByName.xq";
    public static final String getFiltreByNameRequestPath = "../ressources/getFiltreByName.xq";
    private static final String eXistURL = "xmldb:exist://localhost:8080/exist/xmlrpc/IconeLibraryBD";
    public ArrayList<Document> documents;
    public Document documentFinal;
    HashMap<String, ArrayList<String>> params;
    String FinalIconName;
    private Connection connection;
    private URLParser uRLParser;

    public Controler() {
        documents = new ArrayList<Document>();
    }

    public void setFinalIconName(String FinalIconName) {
        this.FinalIconName = FinalIconName;
    }

    public String getFinalIconName() {
        return FinalIconName;
    }

    public HashMap<String, ArrayList<String>> getParams() {
        return params;
    }

    public void setDocumentFinal(Document documentFinal) {
        this.documentFinal = documentFinal;
    }

    public Connection getConnection() {
        return connection;
    }

    public ArrayList<Document> getDocuments() {
        return documents;
    }

    public Document getDocumentFinal() {
        return documentFinal;
    }
    private Document docFiltre;

    public void setDocFiltre(Document filtre) {
        this.docFiltre = filtre;
    }

    public Document getDocFiltre() {
        return docFiltre;
    }
    

    public void createIcon(String URL) throws XMLDBException, IOException {
        //Parser l'URL
        parseURL(URL);

        //Connexion à la BDD eXist
        connection();

        //Récupérer la liste des noms
        params = getURLParser().getUrlParsed();
        ArrayList<String> names = params.get(getURLParser().getArgName(0));
        ArrayList<String> tailles = params.get(getURLParser().getArgName(1));
        ArrayList<String> offsetXs = params.get(getURLParser().getArgName(2));
        ArrayList<String> offsetYs = params.get(getURLParser().getArgName(3));
        ArrayList<String> commands = params.get(getURLParser().getArgName(4));

        String nomFiltre = "";
        String urlFiltre = "";
        if (!params.get("nomFiltre").isEmpty()) {
            nomFiltre = params.get("nomFiltre").get(0);
            urlFiltre += "filter:url(#";
            urlFiltre += nomFiltre;
            urlFiltre += ")";
        }

        FinalIconName = params.get("nomIconeFinal").get(0);

        HashMap<String, Object> paramsQuery = new HashMap<String, Object>();

        paramsQuery.put(getURLParser().getArgName(0), names.get(0));
        paramsQuery.put(getURLParser().getArgName(2), offsetXs.get(0));
        paramsQuery.put(getURLParser().getArgName(3), offsetYs.get(0));
        paramsQuery.put(getURLParser().getArgName(1), Integer.valueOf(tailles.get(0)));
        paramsQuery.put("filtername", urlFiltre);

        XQueryRequest xQueryRequest = getConnection().getXQueryRequest();

        getDocuments().add(xmlVersDOMDocument(xQueryRequest.executeRequeteXQuery(getIconeByNameRequestPath, paramsQuery)));

        for (int i = 1; i < names.size(); i++) {

            paramsQuery.put(getURLParser().getArgName(0), names.get(i));
            paramsQuery.put(getURLParser().getArgName(2), offsetXs.get(i));
            paramsQuery.put(getURLParser().getArgName(3), offsetYs.get(i));
            paramsQuery.put(getURLParser().getArgName(1), Integer.valueOf(tailles.get(0)));
            paramsQuery.put("coeff", Float.valueOf(tailles.get(i)));
            paramsQuery.put("filtername", urlFiltre);
            //r�cuperer les SVGDocument � l'aide d'une requete XQuery
            getDocuments().add(xmlVersDOMDocument(xQueryRequest.executeRequeteXQuery(Controler.getSubIconeByNameRequestPath, paramsQuery)));
        }

        combine();

        if (commands.contains("filtre")) {
            getFiltre(xQueryRequest, nomFiltre);
            setFiltre(nomFiltre);
        }
    }

    public void DocumentToImage(Document doc, TypeImage type, ServletOutputStream ostream) throws TranscoderException, IOException {
        ImageTranscoder t = null;
        switch (type) {
            case JPEG:
                t = new JPEGTranscoder();
                t.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(.8));
                break;
            case PNG:
                t = new PNGTranscoder();
                break;
            case TIFF:
                t = new TIFFTranscoder();
                break;
        }
        TranscoderInput input = new TranscoderInput(doc);
        TranscoderOutput output = new TranscoderOutput(ostream);
        // Perform the transcoding.
        t.transcode(input, output);

        ostream.flush();
    }

    /**
     * Method that convert a Stream to a String .
     * @param is
     * @return the String converted
     */
    public static String convertStreamToString(Reader is) throws IOException {
        /*
         * To convert the InputStream to String we use the BufferedReader.readLine()
         * method. We iterate until the BufferedReader return null which means
         * there's no more data to read. Each line will appended to a StringBuilder
         * and returned as String.
         */
        BufferedReader reader = new BufferedReader(is);
        StringBuilder sb = new StringBuilder();

        String line = null;
        
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
 
        return sb.toString();
    }

    public void connection() throws XMLDBException {
        connection = new Connection();
        connection.CreateConnection(eXistURL, "admin", "admin");
    }

    public void parseURL(String URL) {
        uRLParser = new URLParser();
        uRLParser.parseURL(URL);
        uRLParser.controlParsedURL();
    }

    public URLParser getURLParser() {
        return uRLParser;
    }

    public void getFiltre(XQueryRequest request, String name) throws IOException {
        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("name", name);
        setDocFiltre(xmlVersDOMDocument(request.executeRequeteXQuery(getFiltreByNameRequestPath, params)));
    //Commons.serialisation(filtre, System.out);
    }

    public void setFiltre(String nomFiltre) {
        combine(getDocumentFinal(), getDocFiltre());
    }

    /**
     * Method that combine the SVG Documents .
     */
    public void combine() {
        if (getDocuments().size() == 1) {
            setDocumentFinal(getDocuments().get(0));
        }
        Node parentNode = getDocuments().get(0).getFirstChild();
        for (int i = 1; i < getDocuments().size(); i++) {
            Node document = getDocuments().get(i).getFirstChild();
            parentNode.appendChild(getDocuments().get(0).importNode(document, true));
        }
        setDocumentFinal(getDocuments().get(0));
    }

    /**
     * Method that combine a Document with a filter .
     */
    public void combine(Document doc, Document filtre) {
        if (doc == null) {
            return;
        }
        if (filtre == null) {
            return;
        }
        Node parentNode = doc.getFirstChild();
        Node childNode = filtre.getFirstChild();
        parentNode.appendChild(doc.importNode(childNode, true));
    }

    /**
     * Method that convert an xml to a DOMDocument 
     * @param xml
     * @return the DOMDocument 
     */
    public Document xmlVersDOMDocument(String xml) throws IOException{
        
            InputStream in = new ByteArrayInputStream(xml.getBytes());
            String parser = XMLResourceDescriptor.getXMLParserClassName();
            SAXDocumentFactory f = new SAXDocumentFactory(DOMImplementationImpl.getDOMImplementation(), parser);
            Document doc = f.createDocument(null, in);
            //serialisation(doc, System.out);
            return doc;
    }

    /**
     *
     * @param doc document SVG
     * @param out 
     */
    public void serialisation(Document doc, PrintWriter out) throws TransformerConfigurationException, TransformerException {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
  
            Transformer transformer = transformerFactory.newTransformer();

            //transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "true");
            transformer.setOutputProperty(OutputKeys.METHOD, "html");
            transformer.transform(new DOMSource(doc),
                    new StreamResult(out));

    }

    /**
     *
     * @param doc document SVG
     * @param out
     */
    public void serialisation(Document doc, ServletOutputStream out) throws TransformerConfigurationException, TransformerException {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
       
            Transformer transformer = transformerFactory.newTransformer();

            transformer.setOutputProperty(OutputKeys.METHOD, "html");
            transformer.transform(new DOMSource(doc),
                    new StreamResult(out));
        
    }

    /**
     *
     * @param doc document SVG
     * @param out
     */
    public void serialisation(Document doc, PrintStream out) throws TransformerConfigurationException, TransformerException {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        
            Transformer transformer = transformerFactory.newTransformer();

            //transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "true");
            transformer.setOutputProperty(OutputKeys.METHOD, "html");
            transformer.transform(new DOMSource(doc),
                    new StreamResult(out));
        
    }
}
